//
//  overlay.c
//  hdcvt_osd
//
//  Created by gehj on 2023/2/12.
//

#include "overlay.h"

/**
 这个方法单独提取Y轴做覆盖尝试，从左上角开始，对黑白图有意义
 测试文件写法：
 FILE* maskFile = NULL;//小图
//  maskFile = fopen("/Users/gehj/Desktop/OSD-gehj/16x8x1B.raw", "rb");
 maskFile = fopen("/Users/gehj/Desktop/OSD-gehj/3_24*38.RAW", "rb");
 FILE* Bgfile; //背景图
 
 
 //    Bgfile = fopen("/Users/gehj/Desktop/OSD-gehj/3_24*38.RAW", "rb");
     Bgfile = fopen("/Users/gehj/Desktop/OSD-gehj/Y_single_1080P.RAW", "rb");
 
 
 //    int sw = 16, sh=8; //小图在上面叠加
     int sw = 24, sh=38; //小图在上面叠加
 //    int bw = 24, bh = 38;//大图背景图
     int bw = 1920, bh = 1080;
 
 char* yuvs = NULL;
 char* yuvb = NULL;
 yuvs = (char*) malloc (sizeof(char)*sw*sh);
 yuvb = (char*) malloc (sizeof(char)*bw*bh);
 fread (yuvs,1,sw*sh,maskFile); //yuvs=yuvmask往里传的参数
 fread (yuvb,1,bw*bh,Bgfile);//yuv往下面传的参数
 
 
 
 */

int Y_overlay(unsigned char* yuv_mask,
               unsigned char* yuv_bg,
               int w_mask, int h_mask,
               int w_bg,int h_bg)
{
    
    if(w_mask <= 0 || h_mask <= 0 || w_bg <= 0 || w_bg <= 0)
    {
        printf("width or height cannot be less than or equal to 0");
        return -1;
    }
    
    
    if(((w_mask & 0x1) != 0) || ((h_mask & 0x1) != 0)
       || ((w_bg & 0x1) != 0) ||((h_bg & 0x1) != 0) )
    {
        printf("width and height must be multiple of 2.\n");
        return -1;
    }
    
    
    //y_ms，y_bg改变指针所存的内容
    unsigned char* y_ms = yuv_mask;
    unsigned char* y_bg = yuv_bg;//yuvb为原始指针，后面输出要使用
   
    //从图像左上角开始进行y覆盖
    //xy坐标确定：197000/width = y 197000%width = x;
    for (int i = 0; i < h_mask; i++)
    {
        memcpy(y_bg, y_ms, w_mask);//mask覆盖背景
        //换行，指针偏移到行首
        y_bg = y_bg + w_bg;
        y_ms = y_ms + w_mask;
      
    }
    
    return 0;
}



int Y_xy_overlay(unsigned char* yuv_mask,
                  unsigned char* yuv_bg,
                  int w_mask, int h_mask,
                  int w_bg,int h_bg,int x,int y)
{
    if(w_mask <= 0 || h_mask <= 0 || w_bg <= 0 || w_bg <= 0)
    {
        printf("width or height cannot be less than or equal to 0\n");
        return -1;
    }
    
    
    if(((w_mask & 0x1) != 0) || ((h_mask & 0x1) != 0)
       || ((w_bg & 0x1) != 0) ||((h_bg & 0x1) != 0) )
    {
        printf("width and height must be multiple of 2.\n");
        return -1;
    }
    
    
    if(x < 0 || y <0)
    {
        printf("x,y cannot be less than 0\n");
        return -1;
    }
    
    //背景宽度-x坐标位置，测试剩余量宽够不够mask的宽，不够说明x坐标超了，mask被截断
    if( ( w_bg - x < w_mask) || (h_bg-y < h_mask ))
    {
        printf("mask was cut off\n");
        return -1;
    }
    
    
    if((x < 0) || (y <0))
    {
        printf("x,y cannot be less than 0\n");
        return -1;
    }
    
    
    
    //y_ms，y_bg改变指针所存的内容
    unsigned char* y_ms = yuv_mask;
    unsigned char* y_bg = yuv_bg;//yuvb为原始指针，后面输出要使用
    
    //起始字节处
    int offset = y*w_bg + x;
    //从图像左上角开始进行y覆盖
    //xy坐标确定：197000/width = y 197000%width = x;
    for (int row = 0; row < h_mask; row++)
    {
        //mask的地址变化 =  起始地址 + 地址增量
        unsigned char* y_src = y_ms + row*w_mask;
        
        //背景图(目标)的地址变化 = 起始地址 + 地址偏移 + 增量
        unsigned char* y_dst = y_bg + offset+ row*w_bg;

        memcpy(y_dst,y_src,w_mask);//行覆盖
        
        //memcpy(y_bg+offset, y_ms, w_mask);//mask覆盖背景()
        
        
        //换行，指针偏移到行首
        //y_bg = y_bg + w_bg;
        //y_ms = y_ms + w_mask;
        
      
    }
    
    return 0;
}


int YV16_overlay(unsigned char* yuv_mask,
                  unsigned char* yuv_bg,
                  int w_mask, int h_mask,
                  int w_bg,int h_bg,int x,int y)
{
    if(w_mask <= 0 || h_mask <= 0 || w_bg <= 0 || w_bg <= 0)
    {
        printf("width or height cannot be less than or equal to 0\n");
        return -1;
    }
    
    
    if(((w_mask & 0x1) != 0) || ((h_mask & 0x1) != 0)
       || ((w_bg & 0x1) != 0) ||((h_bg & 0x1) != 0) )
    {
        printf("width and height must be multiple of 2.\n");
        return -1;
    }
    
    
    if(x < 0 || y <0)
    {
        printf("x,y cannot be less than 0\n");
        return -1;
    }
    
    //背景宽度-x坐标位置，测试剩余量宽够不够mask的宽，不够说明x坐标超了，mask被截断
    if( ( w_bg - x < w_mask) || (h_bg-y < h_mask ))
    {
        printf("mask was cut off\n");
        return -1;
    }
    
    
    if((x < 0) || (y <0))
    {
        printf("x,y cannot be less than 0\n");
        return -1;
    }
    
    
    
    //以下变量是各分量（yvu）的起始地址
    unsigned char* y_ms = yuv_mask;
    unsigned char* v_ms = y_ms + w_mask*h_mask;
    unsigned char* u_ms = v_ms + w_mask*h_mask/2;
    
    
    unsigned char* y_bg = yuv_bg;//yuvb为原始指针，后面输出要使用
    unsigned char* v_bg = y_bg + w_bg*h_bg;
    unsigned char* u_bg = v_bg + w_bg*h_bg/2;
    
   
    //以下根据(x,y)坐标计算背景图的偏移量
    //y通道偏移量
    int offset_des_y = y*w_bg + x;
    //v通道偏移量
    //x/2:两个Y对应一个V；步进量为width/2，压缩一行
    int offset_des_v = x/2+ y*w_bg/2;
    //u通道偏移量 = v通道偏移量
    //x/2:两个Y对应一个U；步进量为width/2，压缩一行
    int offset_des_u =  x/2 + y*w_bg/2;
    
    
    //mask图像开始覆盖背景图
    for (int row = 0; row < h_mask; row++)
    {
        //mask的地址变化 =  起始地址 + 地址增量
        unsigned char* y_src = y_ms + w_mask*row;
        unsigned char* v_src = v_ms + w_mask*row/2;
        unsigned char* u_src = u_ms + w_mask*row/2;
        
        
        
        
        //背景图(目标)的地址变化 = 起始地址 + 地址偏移 + 增量
        unsigned char* y_dst = y_bg + offset_des_y + row*w_bg;
        unsigned char* v_dst = v_bg + offset_des_v + row*w_bg/2;
        unsigned char* u_dst = u_bg + offset_des_u + row*w_bg/2;
        
        //行覆盖
        memcpy(y_dst,y_src,w_mask);
        memcpy(v_dst, v_src, w_mask/2);
        memcpy(u_dst,u_src,w_mask/2);
        
    }
    
    //TODO free掉中间量
    
    return 0;
    
    
}

//osd增加透明度
int YV16_overlay_transparent(unsigned char* yuv_mask,
                              unsigned char* yuv_bg,
                              int w_mask, int h_mask,
                              int w_bg,int h_bg,
                              int x,int y,
                              float alpha_decimals)
{
    if((w_mask > w_bg) || (h_mask > h_bg))
    {
        printf("mask need to less than background \n");
        if(yuv_mask)
        {
            free(yuv_mask);
            yuv_mask = NULL;
        }
        
        if(yuv_bg)
        {
            free(yuv_bg);
            yuv_bg = NULL;
        }
        exit(-1);
    }
    
    if(x < 0 || y <0)
    {
        printf("x,y cannot be less than 0\n");
        if(yuv_mask)
        {
            free(yuv_mask);
            yuv_mask = NULL;
        }
        
        if(yuv_bg)
        {
            free(yuv_bg);
            yuv_bg = NULL;
        }
        exit(-1);
    }
    
    
   
    
    //背景宽度-x坐标位置，测试剩余量宽够不够mask的宽，不够说明x坐标超了，mask被截断
    if( ( w_bg - x < w_mask) || (h_bg-y < h_mask ))
    {
        printf("mask was cut off\n");
        if(yuv_mask)
        {
            free(yuv_mask);
            yuv_mask = NULL;
        }
        
        if(yuv_bg)
        {
            free(yuv_bg);
            yuv_bg = NULL;
        }
        exit(-1);
       // return -1;
    }
    
    if( alpha_decimals < 0 || alpha_decimals > 1)
    {
        printf("alpha_decimals should be at 0~1\n");
        if(yuv_mask)
        {
            free(yuv_mask);
            yuv_mask = NULL;
        }
        
        if(yuv_bg)
        {
            free(yuv_bg);
            yuv_bg = NULL;
        }
        exit(-1);
        
    }
    
    
    int alpha = alpha_decimals*255;
    //以下变量是各分量（yvu）的起始地址
    unsigned char* y_ms = yuv_mask;
    unsigned char* v_ms = y_ms + w_mask*h_mask;
    unsigned char* u_ms = v_ms + w_mask*h_mask/2;
    
    
    unsigned char* y_bg = yuv_bg;//yuvb为原始指针，后面输出要使用
    unsigned char* v_bg = y_bg + w_bg*h_bg;
    unsigned char* u_bg = v_bg + w_bg*h_bg/2;
    
   
    //以下根据(x,y)坐标计算背景图的偏移量
    //y通道偏移量
    int offset_des_y = y*w_bg + x;
    //v通(= u通道)道偏移量
    //x/2:两个Y对应一个V；步进量为width/2，压缩一行
    int offset_des_v_u = x/2+ y*w_bg/2;
    
    
    //mask图像开始覆盖背景图
    for (int row = 0; row < h_mask; row++)
    {
        //mask的地址变化 =  起始地址 + 地址增量
        unsigned char* y_src = y_ms + w_mask*row;
        unsigned char* v_src = v_ms + w_mask*row/2;
        unsigned char* u_src = u_ms + w_mask*row/2;
        
        //背景图(目标)的地址变化 = 起始地址 + 地址偏移 + 增量
        unsigned char* y_dst = y_bg + offset_des_y + row*w_bg;
        unsigned char* v_dst = v_bg + offset_des_v_u + row*w_bg/2;
        unsigned char* u_dst = u_bg + offset_des_v_u + row*w_bg/2;
        
        //根据alpha值混色 数组方式
        /**
        for (int i = 0; i < w_mask; i++)
        {
            y_dst[i] = ((y_src[i] & 0xFF)*alpha + (y_dst[i]&0xFF)*(255 - alpha))/255;
            
        }
        for (int k = 0; k < w_mask/2; k++)
        {
            v_dst[k] = ((v_src[k] & 0xFF)*alpha + (v_dst[k]&0xFF)*(255 - alpha))/255;
            u_dst[k] = ((u_src[k] & 0xFF)*alpha + (u_dst[k]&0xFF)*(255 - alpha))/255;
        }
        */
        
        //((*y_src & 0xFF)*alpha + (*y_dst & 0xFF)* (255 - alpha)) / 255;
        //根据alpha值混色 指针方式
        int count_y = 0;
        while (count_y < w_mask)
        {
            *y_dst = ((*y_src & 0xFF)*alpha + (*y_dst & 0xFF)* (255 - alpha)) / 255;
            y_src++;
            y_dst++;
            count_y++;
            
           /**
            //u/v覆盖量是y的一半 : 循环中每次要判断，可能会影响效率：单独提出u/v轴进行覆盖；
            if(count < w_mask/2)
            {
                *v_dst = ((*v_src & 0xFF)*alpha + (*v_dst & 0xFF)* (255 - alpha)) / 255;
                *u_dst = ((*u_src & 0xFF)*alpha + (*u_dst & 0xFF)* (255 - alpha)) / 255;
                v_src++;
                u_src++;
                v_dst++;
                u_dst++;
            }
            
            y_src++;
            y_dst++;
            count++;*/
        }
        
        int count_uv = 0;
        while (count_uv < w_mask/2)
        {
            *v_dst = ((*v_src & 0xFF)*alpha + (*v_dst & 0xFF)* (255 - alpha)) / 255;
            *u_dst = ((*u_src & 0xFF)*alpha + (*u_dst & 0xFF)* (255 - alpha)) / 255;
            v_src++;
            u_src++;
            v_dst++;
            u_dst++;
            count_uv++;
        }
        
    }
    
    //TODO free掉中间量
    
    return 0;
    
    
}
